package config

import (
	"log"
	"path/filepath"

	"github.com/go-playground/validator/v10"
	"gopkg.in/ini.v1"
)

// 更多注释请参见 config.ini 的 [Server] 分段
type serverConfigType struct {
	Address        string // 服务器监听地址。
	Port           string // http服务监听端口。
	TLSPort        string // https服务监听端口。
	TLSCertificate string
	TLSPrivateKey  string
	TokenSalt      string `validate:"required"`                    // Token 加盐
	IdSalt         string `validate:"required"`                    // ID 加盐
	DBType         string `validate:"required,oneof=MySQL SQLite"` // 数据库类型
	CASServiceURL  string // 统一认证登录服务地址

	FileUploadType string `validate:"required,oneof=LocalFile QiniuKodo"` // 文件上传服务类型

	StaticResourcePath        string // 静态文件路径
	NotfoundPagePath          string // 404 页面文件位置，相对于 StaticResourcePath 的相对路径，不设置就默认返回“404 not found!!” 的字符串
	SupportVueRoteHistoryMode bool   //是否支持Vue的HistoryMode路由，如果开启，页面将不会返回404，而是直接返回index.html的内容
}

func (s serverConfigType) HttpAddres() string {
	return s.Address + ":" + s.Port
}

func (s serverConfigType) HttpsAddres() string {
	return s.Address + ":" + s.TLSPort
}

func (s serverConfigType) HasTLS() bool {
	return len(s.TLSCertificate) > 0 && len(s.TLSPrivateKey) > 0
}

func (c localFileConfig) GetFinalAccessUrl() string {
	if len(c.AccessURL) > 0 {
		return LocalFile.AccessURL
	}
	if Server.HasTLS() {
		if Server.TLSPort != "443" {
			return "https://" + Server.HttpsAddres()
		} else {
			return "https://" + Server.Address
		}
	} else {
		if Server.TLSPort != "80" {
			return "http://" + Server.HttpAddres()
		} else {
			return "http://" + Server.Address
		}
	}
}

type sqliteConfigType struct {
	DBPath string
}

type mySQLConfigType struct {
	Address  string
	UserName string
	DataBase string
	Password string
}

type userConfigType struct {
	PasswordRule                   string
	TokenExpirationDuration        int64 `validate:"required"`
	TokenRefreshExpirationDuration int64 `validate:"required"`
}

type localFileConfig struct {
	FilaSavePath string `validate:"required"`
	AccessURL    string `validate:"required,endsnotwith=/"`
}

type qiniuKodoFileConfig struct {
	AccessURL                       string `validate:"required,endsnotwith=/"`
	BucketName                      string `validate:"required"`
	IsPrivate                       bool   `validate:"required"`
	DefaultPreivateBucketAccessTime int
	AccessKey                       string `validate:"required"`
	SecretKey                       string `validate:"required"`
}

const (
	DebugMode   = "Debug"
	TestMode    = "Test"
	ReleaseMode = "Release"

	FileUploadTypeLocal     = "LocalFile"
	FileUploadTypeQiniuKodo = "QiniuKodo"
)

var Mode = ReleaseMode

var Server = serverConfigType{Address: "", Port: "80", TLSPort: "443", FileUploadType: FileUploadTypeLocal}
var SQLite = sqliteConfigType{}
var MySQL = mySQLConfigType{}
var User = userConfigType{}
var LocalFile = localFileConfig{}
var QiniuKodo = qiniuKodoFileConfig{}

func Init(configPath string) {
	iniFile, err := ini.Load((configPath))
	if err != nil {
		log.Fatal(err.Error())
	}

	v := validator.New()

	var validate = func(value interface{}) {
		err := v.Struct(value)
		if err != nil {
			log.Fatal(err)
		}
	}

	iniFile.Section("Server").MapTo(&Server)
	validate(Server)
	iniFile.Section("MySQL").MapTo(&MySQL)
	iniFile.Section("SQLite").MapTo(&SQLite)
	if Server.DBType == "MySQL" {
		validate(MySQL)
	} else if Server.DBType == "SQLite" {
		validate(SQLite)
	}
	iniFile.Section("User").MapTo(&User)
	validate(User)
	iniFile.Section("LocalFile").MapTo(&LocalFile)
	iniFile.Section("QiniuKodo").MapTo(&QiniuKodo)

	if Server.FileUploadType == FileUploadTypeLocal {
		validate(LocalFile)
	} else if Server.FileUploadType == FileUploadTypeQiniuKodo {
		validate(QiniuKodo)
	}

	if len(LocalFile.FilaSavePath) != 0 {
		// 转成绝对路径
		absPath, err := filepath.Abs(LocalFile.FilaSavePath)
		if err != nil {
			panic(err)
		}
		LocalFile.FilaSavePath = absPath
	}
}

func NotReleaseMode() bool {
	return Mode != ReleaseMode
}

var BasePath = ""
